using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 分类应用服务实现
    /// 提供分类的完整CRUD操作、层级管理、批量操作等功能
    /// </summary>
    public class CategoryAppService : ICategoryAppService
    {
        private readonly ICategoryRepository _categoryRepository;
        private readonly ILogger<CategoryAppService> _logger;

        public CategoryAppService(
            ICategoryRepository categoryRepository,
            ILogger<CategoryAppService> logger)
        {
            _categoryRepository = categoryRepository;
            _logger = logger;
        }

        #region 基础CRUD操作

        /// <summary>
        /// 创建分类
        /// </summary>
        public async Task<CategoryDto> CreateAsync(CategoryDto dto)
        {
            try
            {
                _logger.LogInformation("开始创建分类: {CategoryName}, 类型: {Type}, 父ID: {ParentId}", 
                    dto.Name, dto.Type, dto.ParentId);

                // 1. 验证分类名称唯一性
                var exists = await ExistsAsync(dto.Name, dto.Type, dto.ParentId);
                if (exists)
                {
                    var message = dto.ParentId.HasValue 
                        ? $"父分类下已存在名为 '{dto.Name}' 的分类"
                        : $"根级分类中已存在名为 '{dto.Name}' 的分类";
                    throw new InvalidOperationException(message);
                }

                // 2. 生成URL别名
                var slug = GenerateSlug(dto.Name);
                
                // 3. 创建分类实体
                var category = new Category
                {
                    Name = dto.Name.Trim(),
                    Slug = slug,
                    Type = dto.Type.ToLower(),
                    ParentId = dto.ParentId,
                    Description = dto.Description?.Trim(),
                    SortOrder = dto.SortOrder,
                    Status = dto.IsEnabled ? (byte)1 : (byte)0,
                    CreatedBy = 1, // TODO: 从当前用户上下文获取
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await _categoryRepository.AddAsync(category);
                await _categoryRepository.SaveChangesAsync();

                _logger.LogInformation("分类创建成功: {CategoryName} (ID: {CategoryId})", 
                    dto.Name, category.Id);

                return MapToDto(category);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分类创建失败: {CategoryName}", dto.Name);
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取分类
        /// </summary>
        public async Task<CategoryDto?> GetByIdAsync(long id)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                return category == null ? null : MapToDto(category);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取分类失败: ID {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 更新分类
        /// </summary>
        public async Task<CategoryDto> UpdateAsync(long id, CategoryDto dto)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                if (category == null)
                {
                    throw new InvalidOperationException($"分类 ID {id} 不存在");
                }

                // 验证名称唯一性（排除自己）
                var exists = await ExistsAsync(dto.Name, dto.Type, dto.ParentId, id);
                if (exists)
                {
                    throw new InvalidOperationException($"分类名称 '{dto.Name}' 已存在");
                }

                // 更新基本信息
                category.Name = dto.Name.Trim();
                category.Slug = GenerateSlug(dto.Name);
                category.Type = dto.Type.ToLower();
                category.ParentId = dto.ParentId;
                category.Description = dto.Description?.Trim();
                category.SortOrder = dto.SortOrder;
                category.Status = dto.IsEnabled ? (byte)1 : (byte)0;
                category.UpdatedBy = 1; // TODO: 从当前用户上下文获取
                category.UpdatedAt = DateTime.UtcNow;

                await _categoryRepository.UpdateAsync(category);
                await _categoryRepository.SaveChangesAsync();

                _logger.LogInformation("分类更新成功: {CategoryId}", id);
                return MapToDto(category);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分类更新失败: ID {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 删除分类
        /// </summary>
        public async Task<bool> DeleteAsync(long id, bool deleteChildren = false)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                if (category == null)
                {
                    return false;
                }

                // 检查是否有子分类
                var children = await GetChildrenAsync(id);
                if (children.Any())
                {
                    if (!deleteChildren)
                    {
                        throw new InvalidOperationException("该分类下有子分类，请先删除子分类或选择同时删除");
                    }

                    // 递归删除所有子分类
                    foreach (var child in children)
                    {
                        await DeleteAsync(child.Id, true);
                    }
                }

                // TODO: 检查分类下是否有内容，根据业务需求决定是否允许删除

                await _categoryRepository.DeleteAsync(category);
                await _categoryRepository.SaveChangesAsync();

                _logger.LogInformation("分类删除成功: {CategoryId}", id);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分类删除失败: ID {CategoryId}", id);
                throw;
            }
        }

        #endregion

        #region 查询操作

        /// <summary>
        /// 检查分类是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(string name, string type, long? parentId = null, long? excludeId = null)
        {
            try
            {
                return await _categoryRepository.ExistsAsync(c => 
                    c.Name == name && 
                    c.Type == type.ToLower() && 
                    c.ParentId == parentId &&
                    (excludeId == null || c.Id != excludeId));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查分类是否存在失败: {Name}, {Type}", name, type);
                throw;
            }
        }

        /// <summary>
        /// 根据类型获取分类列表
        /// </summary>
        public async Task<List<CategoryDto>> GetByTypeAsync(string type)
        {
            try
            {
                var categories = await _categoryRepository.FindAsync(c => 
                    c.Type == type.ToLower() && c.Status == 1);
                
                return categories.OrderBy(c => c.SortOrder)
                    .ThenBy(c => c.Name)
                    .Select(MapToDto)
                    .ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据类型获取分类列表失败: {Type}", type);
                throw;
            }
        }

        /// <summary>
        /// 根据路径获取分类
        /// </summary>
        public async Task<CategoryDto?> GetByPathAsync(string path)
        {
            try
            {
                // 这里需要根据实际需求实现路径查找逻辑
                // 由于当前Category实体没有Path字段，暂时使用Slug匹配
                var slug = path.TrimStart('/');
                var category = await _categoryRepository.FindSingleAsync(c => c.Slug == slug);
                return category == null ? null : MapToDto(category);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据路径获取分类失败: {Path}", path);
                throw;
            }
        }

        /// <summary>
        /// 获取子分类
        /// </summary>
        public async Task<List<CategoryDto>> GetChildrenAsync(long parentId, bool includeDisabled = false)
        {
            try
            {
                var categories = await _categoryRepository.FindAsync(c => 
                    c.ParentId == parentId &&
                    (includeDisabled || c.Status == 1));
                    
                return categories.OrderBy(c => c.SortOrder)
                    .ThenBy(c => c.Name)
                    .Select(MapToDto)
                    .ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取子分类失败: ParentId {ParentId}", parentId);
                throw;
            }
        }

        /// <summary>
        /// 获取祖先分类
        /// </summary>
        public async Task<List<CategoryDto>> GetAncestorsAsync(long id)
        {
            try
            {
                var ancestors = new List<CategoryDto>();
                var current = await _categoryRepository.GetByIdAsync(id);

                while (current?.ParentId != null)
                {
                    current = await _categoryRepository.GetByIdAsync(current.ParentId.Value);
                    if (current != null)
                    {
                        ancestors.Insert(0, MapToDto(current));
                    }
                }

                return ancestors;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取祖先分类失败: ID {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 获取后代分类
        /// </summary>
        public async Task<List<CategoryDto>> GetDescendantsAsync(long id)
        {
            try
            {
                var descendants = new List<CategoryDto>();
                await GetDescendantsRecursive(id, descendants);
                return descendants;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取后代分类失败: ID {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 分页获取分类列表
        /// </summary>
        public async Task<PagedResultDto<CategoryDto>> GetPagedListAsync(PagedQueryDto query)
        {
            try
            {
                query.Normalize();
                
                // 构建查询条件
                var predicate = BuildQueryPredicate(query);
                var totalCount = await _categoryRepository.CountAsync(predicate);
                
                // 获取分页数据
                var result = await _categoryRepository.GetPagedAsync(
                    query.PageIndex,
                    query.PageSize,
                    predicate);

                return new PagedResultDto<CategoryDto>
                {
                    Items = result.Items.Select(MapToDto).ToList(),
                    TotalCount = result.Total,
                    PageIndex = query.PageIndex,
                    PageSize = query.PageSize
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页获取分类列表失败");
                throw;
            }
        }

        /// <summary>
        /// 获取树形分类列表
        /// </summary>
        public async Task<List<CategoryDto>> GetTreeAsync(string? type = null, long? parentId = null)
        {
            try
            {
                var categories = await _categoryRepository.FindAsync(c => 
                    c.ParentId == parentId &&
                    (type == null || c.Type == type.ToLower()) &&
                    c.Status == 1);

                var result = new List<CategoryDto>();

                foreach (var category in categories.OrderBy(c => c.SortOrder).ThenBy(c => c.Name))
                {
                    var dto = MapToDto(category);
                    dto.Children = await GetTreeAsync(type, category.Id);
                    result.Add(dto);
                }

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取树形分类列表失败: Type {Type}, ParentId {ParentId}", type, parentId);
                throw;
            }
        }

        #endregion

        #region 批量和高级操作

        /// <summary>
        /// 批量删除分类
        /// </summary>
        public async Task<bool> BatchDeleteAsync(List<long> ids, bool deleteChildren = false)
        {
            try
            {
                _logger.LogInformation("开始批量删除分类: {CategoryIds}", string.Join(",", ids));

                foreach (var id in ids)
                {
                    await DeleteAsync(id, deleteChildren);
                }

                _logger.LogInformation("批量删除分类成功");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除分类失败: {CategoryIds}", string.Join(",", ids));
                throw;
            }
        }

        /// <summary>
        /// 移动分类
        /// </summary>
        public async Task<bool> MoveAsync(long id, long? newParentId)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                if (category == null)
                {
                    return false;
                }

                // 防止将分类移动到自己的子分类下
                if (newParentId.HasValue)
                {
                    var descendants = await GetDescendantsAsync(id);
                    if (descendants.Any(d => d.Id == newParentId.Value))
                    {
                        throw new InvalidOperationException("不能将分类移动到自己的子分类下");
                    }
                }

                category.ParentId = newParentId;
                category.UpdatedBy = 1; // TODO: 从当前用户上下文获取
                category.UpdatedAt = DateTime.UtcNow;

                await _categoryRepository.UpdateAsync(category);
                await _categoryRepository.SaveChangesAsync();

                _logger.LogInformation("分类移动成功: {CategoryId} -> ParentId {NewParentId}", id, newParentId);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分类移动失败: CategoryId {CategoryId}, NewParentId {NewParentId}", id, newParentId);
                throw;
            }
        }

        /// <summary>
        /// 批量更新排序
        /// </summary>
        public async Task<bool> BatchUpdateSortAsync(Dictionary<long, int> sortData)
        {
            try
            {
                _logger.LogInformation("开始批量更新分类排序");

                foreach (var kvp in sortData)
                {
                    var category = await _categoryRepository.GetByIdAsync(kvp.Key);
                    if (category != null)
                    {
                        category.SortOrder = kvp.Value;
                        category.UpdatedBy = 1; // TODO: 从当前用户上下文获取
                        category.UpdatedAt = DateTime.UtcNow;
                        await _categoryRepository.UpdateAsync(category);
                    }
                }

                await _categoryRepository.SaveChangesAsync();
                _logger.LogInformation("批量更新分类排序成功");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量更新分类排序失败");
                throw;
            }
        }

        /// <summary>
        /// 启用/禁用分类
        /// </summary>
        public async Task<bool> SetEnabledAsync(long id, bool enabled)
        {
            try
            {
                var category = await _categoryRepository.GetByIdAsync(id);
                if (category == null)
                {
                    return false;
                }

                category.Status = enabled ? (byte)1 : (byte)0;
                category.UpdatedBy = 1; // TODO: 从当前用户上下文获取
                category.UpdatedAt = DateTime.UtcNow;

                await _categoryRepository.UpdateAsync(category);
                await _categoryRepository.SaveChangesAsync();

                _logger.LogInformation("分类状态更新成功: CategoryId {CategoryId}, Enabled {Enabled}", id, enabled);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分类状态更新失败: CategoryId {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 更新分类内容统计
        /// </summary>
        public async Task<bool> UpdateContentCountAsync(long id)
        {
            try
            {
                // TODO: 根据实际业务需求实现内容统计
                // 例如：统计该分类下的文章数量、产品数量等
                
                // 模拟异步操作，避免编译警告
                await Task.Delay(1);
                
                _logger.LogInformation("内容统计更新成功: CategoryId {CategoryId}", id);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "内容统计更新失败: CategoryId {CategoryId}", id);
                throw;
            }
        }

        /// <summary>
        /// 导出分类数据
        /// </summary>
        public async Task<byte[]> ExportAsync(string? type = null)
        {
            try
            {
                var categories = type == null 
                    ? await _categoryRepository.GetAllAsync()
                    : await _categoryRepository.FindAsync(c => c.Type == type.ToLower());

                var json = JsonSerializer.Serialize(categories.Select(MapToDto), new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    WriteIndented = true
                });

                return System.Text.Encoding.UTF8.GetBytes(json);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出分类数据失败: Type {Type}", type);
                throw;
            }
        }

        /// <summary>
        /// 导入分类数据
        /// </summary>
        public async Task<List<CategoryDto>> ImportAsync(byte[] data)
        {
            try
            {
                var json = System.Text.Encoding.UTF8.GetString(data);
                var importData = JsonSerializer.Deserialize<List<CategoryDto>>(json, new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                var result = new List<CategoryDto>();
                
                if (importData != null)
                {
                    foreach (var dto in importData)
                    {
                        // 检查是否已存在
                        var exists = await ExistsAsync(dto.Name, dto.Type, dto.ParentId);
                        if (!exists)
                        {
                            var created = await CreateAsync(dto);
                            result.Add(created);
                        }
                    }
                }

                _logger.LogInformation("导入分类数据成功，共导入 {Count} 个分类", result.Count);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导入分类数据失败");
                throw;
            }
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 将实体映射为DTO
        /// </summary>
        private CategoryDto MapToDto(Category category)
        {
            return new CategoryDto
            {
                Id = category.Id,
                Name = category.Name,
                Type = category.Type,
                ParentId = category.ParentId,
                Description = category.Description,
                SortOrder = category.SortOrder,
                IsEnabled = category.Status == 1,
                CreatedAt = category.CreatedAt,
                UpdatedAt = category.UpdatedAt
            };
        }

        /// <summary>
        /// 生成URL别名
        /// </summary>
        private string GenerateSlug(string name)
        {
            // 简单的slug生成，可以根据需要优化
            return name.ToLower()
                .Replace(" ", "-")
                .Replace("　", "-")
                .Replace("/", "-");
        }

        /// <summary>
        /// 递归获取后代分类
        /// </summary>
        private async Task GetDescendantsRecursive(long parentId, List<CategoryDto> descendants)
        {
            var children = await GetChildrenAsync(parentId, true);
            
            foreach (var child in children)
            {
                descendants.Add(child);
                await GetDescendantsRecursive(child.Id, descendants);
            }
        }

        /// <summary>
        /// 构建查询谓词
        /// </summary>
        private System.Linq.Expressions.Expression<Func<Category, bool>> BuildQueryPredicate(PagedQueryDto query)
        {
            return c => 
                (string.IsNullOrEmpty(query.Keyword) || 
                 c.Name.Contains(query.Keyword) || 
                 (c.Description != null && c.Description.Contains(query.Keyword))) &&
                (query.Status == null || c.Status == query.Status) &&
                (query.CreatedFrom == null || c.CreatedAt >= query.CreatedFrom) &&
                (query.CreatedTo == null || c.CreatedAt <= query.CreatedTo);
        }

        /// <summary>
        /// 获取排序表达式
        /// </summary>
        private string GetSortExpression(string? sortBy, bool descending)
        {
            var column = sortBy?.ToLower() switch
            {
                "name" => "Name",
                "createdat" => "CreatedAt",
                "updatedat" => "UpdatedAt",
                _ => "SortOrder"
            };

            return descending ? $"{column} desc" : column;
        }

        #endregion
    }
}
